package com.sneakxy.mybatis.commons.repository.query.domain.criterions;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;

import com.sneakxy.mybatis.commons.dialect.Dialect;
import com.sneakxy.mybatis.commons.orm.mapping.MybatisColumn;
import com.sneakxy.mybatis.commons.repository.config.MybatisCommonsConfiguration;
import com.sneakxy.mybatis.commons.repository.query.domain.Criterion;

/**
 * @author 潜行的青衣
 */
@SuppressWarnings("serial")
public abstract class AbstractCriterion implements Criterion {

	private Class<?> domainClass;
	
	private String property;
	
	private Object value;
	
	private String open = "";
	
	private String close = "";
	
	public AbstractCriterion(Class<?> domainClass, String property, Object value) {
		this.domainClass = domainClass;
		this.property = property;
		this.value = value;
	}
	
	@Override
	public List<MybatisColumn> getColumns(TypeHandlerRegistry typeHandlerRegistry, String prefix) {
		return MybatisColumn.getColumns(typeHandlerRegistry, domainClass, this.getProperty(), prefix);
	}
	
	public Dialect getDialect(Configuration config) {
		return ((MybatisCommonsConfiguration) config).getDialect();
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.repository.query.domain.Criterion#getProperty()
	 */
	@Override
	public String getProperty() {
		return this.property;
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.repository.query.domain.Criterion#getValue()
	 */
	@Override
	public Object getValue() {
		return this.value;
	}

	protected String getRemove() {
		int dotIndex = StringUtils.lastIndexOf(this.getProperty(), ".") + 1;
		return new StringBuilder().append(".").append(StringUtils.substring(this.getProperty(), dotIndex)).toString();
	}
	
	public Class<?> getDomainClass() {
		return domainClass;
	}

	public String getOpen() {
		return open;
	}

	public void setOpen(String open) {
		this.open = open;
	}

	public String getClose() {
		return close;
	}

	public void setClose(String close) {
		this.close = close;
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder()
				.append(this.value)
				.append(this.property)
				.append(this.domainClass).toHashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(!this.getClass().isAssignableFrom(obj.getClass())) {
			return false;
		}
		AbstractCriterion criterion = (AbstractCriterion) obj;
		return new EqualsBuilder()
			.append(this.value, criterion.value)
			.append(this.property, criterion.property)
			.append(this.domainClass, criterion.domainClass).isEquals();
	}

}
